package ru.tulupov.scheduledrunner.util;

import java.util.LinkedList;

/**
 * Task executor
 * 
 * @author <a href="mailto:zhekka3@gmail.com">Eugene Tulupov</a>
 */
public class ThreadPool {
	private LinkedList<Runnable> queue;
	private Thread[] workers;

	/**
	 * Gets the queue size
	 * 
	 * @return the queue size
	 */
	public int queueSize() {
		synchronized (queue) {
			return queue.size();
		}
	}

	/**
	 * Gets the workers count
	 * 
	 * @return the workers count
	 */
	public int size() {
		return workers.length;
	}

	/**
	 * Creates a thread pool with specified workers count
	 * 
	 * @param count
	 *            the workers count
	 */
	public ThreadPool(int count) {
		queue = new LinkedList<Runnable>();
		workers = new Thread[count];
		for (int i = 0; i < workers.length; i++) {
			workers[i] = new Worker();
			workers[i].start();
		}

	}

	/**
	 * Puts the task into the run queue and execute it
	 * 
	 * @param runnable
	 *            the task
	 */
	public void execute(Runnable runnable) {
		synchronized (queue) {
			queue.addLast(runnable);
			queue.notifyAll();
		}
	}

	private class Worker extends Thread {

		@Override
		public void run() {
			while (true) {
				Runnable runnable;
				synchronized (queue) {
					while (queue.isEmpty()) {
						try {
							queue.wait();
						} catch (InterruptedException e) {
							break;
						}
					}

					runnable = (Runnable) queue.removeFirst();
				}

				try {
					runnable.run();
				} catch (Throwable e) {
					e.printStackTrace();
				}
			}
		}
	}
}